using Beauty.Net.Consul;
using Beauty.Net.Consul.Core;
using Beauty.Net.Ocelot;
using Beauty.Net.Ocelot.Core;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace Beauty.Net.Integration;

/// <summary>
/// 服务发现和网关集成扩展
/// </summary>
public static class ServiceDiscoveryAndGatewayExtensions
{
    /// <summary>
    /// 添加Consul服务发现和Ocelot网关集成
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configuration">配置对象</param>
    /// <returns>Ocelot构建器</returns>
    public static IOcelotBuilder AddServiceDiscoveryAndGateway(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        // 获取Consul和Ocelot的配置
        var consulOptions = configuration.GetSection("Consul").Get<ConsulOptions>() ?? new ConsulOptions();
        var ocelotOptions = configuration.GetSection("Ocelot").Get<OcelotOptions>() ?? new OcelotOptions();
        
        // 配置Ocelot使用Consul服务发现
        if (consulOptions.Enabled && ocelotOptions.EnableConsulServiceDiscovery)
        {
            // 同步Consul配置到Ocelot
            ocelotOptions.ConsulDiscovery = new ConsulDiscoveryOptions
            {
                Host = consulOptions.Address.Split(":")[0],
                Port = int.TryParse(consulOptions.Address.Split(":").Last(), out var port) ? port : 8500,
                Token = consulOptions.Token,
                Namespace = consulOptions.Namespace,
                EnableHealthCheck = consulOptions.EnableHealthCheck
            };
            
            // 保存更新后的Ocelot配置
            configuration.GetSection("Ocelot").Bind(ocelotOptions);
        }
        
        // 添加Consul服务
        if (consulOptions.Enabled)
        {
            services.AddConsul(configuration);
        }
        
        // 添加Ocelot网关服务
        var builder = services.AddOcelotGateway(configuration);
        
        return builder;
    }
    
    /// <summary>
    /// 添加Consul服务发现和Ocelot网关集成（使用配置委托）
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configureConsul">Consul配置委托</param>
    /// <param name="configureOcelot">Ocelot配置委托</param>
    /// <returns>Ocelot构建器</returns>
    public static IOcelotBuilder AddServiceDiscoveryAndGateway(
        this IServiceCollection services,
        Action<ConsulOptions> configureConsul,
        Action<OcelotOptions> configureOcelot)
    {
        var consulOptions = new ConsulOptions();
        var ocelotOptions = new OcelotOptions();
        
        // 配置Consul
        configureConsul(consulOptions);
        
        // 配置Ocelot
        configureOcelot(ocelotOptions);
        
        // 如果启用了Consul和Ocelot服务发现，同步配置
        if (consulOptions.Enabled && !ocelotOptions.EnableConsulServiceDiscovery)
        {
            ocelotOptions.EnableConsulServiceDiscovery = true;
            ocelotOptions.ConsulDiscovery = new ConsulDiscoveryOptions
            {
                Host = consulOptions.Address.Split(":")[0],
                Port = int.TryParse(consulOptions.Address.Split(":").Last(), out var port) ? port : 8500,
                Token = consulOptions.Token,
                Namespace = consulOptions.Namespace
            };
        }
        
        // 添加Consul服务
        if (consulOptions.Enabled)
        {
            services.AddConsul(options => configureConsul(options));
        }
        
        // 添加Ocelot网关服务
        var builder = services.AddOcelotGateway(options => configureOcelot(options));
        
        return builder;
    }
    
    /// <summary>
    /// 配置微服务架构（同时配置服务发现和网关）
    /// </summary>
    /// <param name="builder">Web应用程序构建器</param>
    /// <returns>Web应用程序构建器</returns>
    public static WebApplicationBuilder ConfigureMicroservices(
        this WebApplicationBuilder builder)
    {
        // 添加服务发现和网关
        builder.Services.AddServiceDiscoveryAndGateway(builder.Configuration);
        
        // 配置服务地址
        builder.Services.ConfigureConsulServiceAddress(builder.Environment);
        
        return builder;
    }
    
    /// <summary>
    /// 使用微服务中间件（服务发现和网关）
    /// </summary>
    /// <param name="app">应用程序构建器</param>
    /// <param name="useGateway">是否使用网关</param>
    /// <returns>应用程序构建器</returns>
    public static IApplicationBuilder UseMicroservices(
        this IApplicationBuilder app,
        bool useGateway = true)
    {
        // 配置异常处理
        app.ConfigureOcelotExceptionHandling();
        
        // 配置Ocelot验证
        app.UseOcelotValidation();
        
        // 如果启用了网关
        if (useGateway)
        {
            app.UseOcelotGateway();
        }
        
        return app;
    }
    
    /// <summary>
    /// 配置网关路由（IServiceCollection扩展）
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="routes">路由配置动作</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection ConfigureGatewayRoutes(
        this IServiceCollection services,
        Action<List<ApiRouteOptions>> routes)
    {
        // 在启动时配置路由
        services.AddHostedService<ConfigureRoutesHostedService>(sp =>
        {
            var configurationManager = sp.GetRequiredService<IOcelotConfigurationManager>();
            var routeList = new List<ApiRouteOptions>();
            routes(routeList);
            return new ConfigureRoutesHostedService(configurationManager, routeList);
        });
        
        return services;
    }
    
    /// <summary>
    /// 配置网关路由（IOcelotBuilder扩展）
    /// </summary>
    /// <param name="builder">Ocelot构建器</param>
    /// <param name="routes">路由配置动作</param>
    /// <returns>Ocelot构建器</returns>
    public static IOcelotBuilder ConfigureGatewayRoutes(
        this IOcelotBuilder builder,
        Action<List<ApiRouteOptions>> routes)
    {
        var routeList = new List<ApiRouteOptions>();
        routes(routeList);
        
        return builder.ConfigureRoutes(routeList);
    }
    
    /// <summary>
    /// 添加默认的健康检查端点
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddDefaultHealthChecks(this IServiceCollection services)
    {
        services.AddHealthChecks();
        return services;
    }
    
    /// <summary>
    /// 使用默认的健康检查端点
    /// </summary>
    /// <param name="app">应用程序构建器</param>
    /// <param name="pattern">健康检查路径</param>
    /// <returns>应用程序构建器</returns>
    public static IApplicationBuilder UseDefaultHealthChecks(
        this IApplicationBuilder app,
        string pattern = "/health")
    {
        app.UseHealthChecks(pattern);
        return app;
    }
}